/*

 * MpegInfo.

 * 

 * JavaZOOM : jlgui@javazoom.net http://www.javazoom.net

 * 

 * ----------------------------------------------------------------------- This

 * program is free software; you can redistribute it and/or modify it under the

 * terms of the GNU Library General Public License as published by the Free

 * Software Foundation; either version 2 of the License, or (at your option) any

 * later version.

 * 

 * This program is distributed in the hope that it will be useful, but WITHOUT

 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS

 * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more

 * details.

 * 

 * You should have received a copy of the GNU Library General Public License

 * along with this program; if not, write to the Free Software Foundation, Inc.,

 * 675 Mass Ave, Cambridge, MA 02139, USA.

 * ----------------------------------------------------------------------

 */



package lius.index.audio;



import java.io.File;

import java.io.IOException;

import java.io.InputStream;

import java.net.URL;

import java.util.Iterator;

import java.util.Map;

import java.util.Vector;



import javax.sound.sampled.AudioFileFormat;

import javax.sound.sampled.AudioSystem;

import javax.sound.sampled.UnsupportedAudioFileException;



import org.tritonus.share.sampled.file.TAudioFileFormat;



/**

 * This class gives information (audio format and comments) about MPEG file or

 * URL.

 */

public class MpegInfo implements TagInfo {



	protected int channels = -1;

	protected String channelsMode = null;

	protected String version = null;

	protected int rate = 0;

	protected String layer = null;

	protected String emphasis = null;

	protected int nominalbitrate = 0;

	protected long total = 0;

	protected String vendor = null;

	protected String location = null;

	protected long size = 0;

	protected boolean copyright = false;

	protected boolean crc = false;

	protected boolean original = false;

	protected boolean priv = false;

	protected boolean vbr = false;

	protected int track = -1;

	protected String year = null;

	protected String genre = null;

	protected String title = null;

	protected String artist = null;

	protected String album = null;

	protected Vector comments = null;



	/**

	 * Constructor.

	 */

	public MpegInfo() {

		super();

	}



	/**

	 * Load and parse MPEG info from File.

	 *

	 * @param input

	 * @throws IOException

	 */

	public void load( File input ) throws IOException,

			UnsupportedAudioFileException {

		size = input.length();

		location = input.getPath();

		loadInfo( input );

	}



	/**

	 * Load and parse MPEG info from URL.

	 *

	 * @param input

	 * @throws IOException

	 * @throws UnsupportedAudioFileException

	 */

	public void load( URL input ) throws IOException,

			UnsupportedAudioFileException {

		location = input.toString();

		loadInfo( input );

	}



	/**

	 * Load and parse MPEG info from InputStream.

	 *

	 * @param input

	 * @throws IOException

	 * @throws UnsupportedAudioFileException

	 */

	public void load( InputStream input ) throws IOException,

			UnsupportedAudioFileException {

		loadInfo( input );

	}



	/**

	 * Load info from input stream.

	 *

	 * @param input

	 * @throws IOException

	 * @throws UnsupportedAudioFileException

	 */

	protected void loadInfo( InputStream input ) throws IOException,

			UnsupportedAudioFileException {

		AudioFileFormat aff = AudioSystem.getAudioFileFormat( input );

		loadInfo( aff );

	}



	/**

	 * Load MP3 info from file.

	 *

	 * @param file

	 * @throws IOException

	 * @throws UnsupportedAudioFileException

	 */

	protected void loadInfo( File file ) throws IOException,

			UnsupportedAudioFileException {

		AudioFileFormat aff = AudioSystem.getAudioFileFormat( file );

		loadInfo( aff );

	}



	/**

	 * Load info from AudioFileFormat.

	 *

	 * @param aff

	 */

	protected void loadInfo( AudioFileFormat aff )

			throws UnsupportedAudioFileException {

		String type = aff.getType().toString();

		if ( !type.equalsIgnoreCase( "mp3" ) )

			throw new UnsupportedAudioFileException( "Not MP3 audio format" );

		if ( aff instanceof TAudioFileFormat ) {

			Map props = ( (TAudioFileFormat) aff ).properties();

			if ( props.containsKey( "mp3.channels" ) )

				channels = ( (Integer) props.get( "mp3.channels" ) ).intValue();

			if ( props.containsKey( "mp3.frequency.hz" ) )

				rate = ( (Integer) props.get( "mp3.frequency.hz" ) ).intValue();

			if ( props.containsKey( "mp3.bitrate.nominal.bps" ) )

				nominalbitrate = ( (Integer) props

						.get( "mp3.bitrate.nominal.bps" ) ).intValue();

			if ( props.containsKey( "mp3.version.layer" ) )

				layer = "Layer " + (String) props.get( "mp3.version.layer" );

			if ( props.containsKey( "mp3.version.mpeg" ) ) {

				version = (String) props.get( "mp3.version.mpeg" );

				if ( version.equals( "1" ) )

					version = "MPEG1";

				else if ( version.equals( "2" ) )

					version = "MPEG2-LSF";

				else if ( version.equals( "2.5" ) )

					version = "MPEG2.5-LSF";

			}

			if ( props.containsKey( "mp3.mode" ) ) {

				int mode = ( (Integer) props.get( "mp3.mode" ) ).intValue();

				if ( mode == 0 )

					channelsMode = "Stereo";

				else if ( mode == 1 )

					channelsMode = "Joint Stereo";

				else if ( mode == 2 )

					channelsMode = "Dual Channel";

				else if ( mode == 3 )

					channelsMode = "Single Channel";

			}

			if ( props.containsKey( "mp3.crc" ) )

				crc = ( (Boolean) props.get( "mp3.crc" ) ).booleanValue();

			if ( props.containsKey( "mp3.vbr" ) )

				vbr = ( (Boolean) props.get( "mp3.vbr" ) ).booleanValue();

			if ( props.containsKey( "mp3.copyright" ) )

				copyright = ( (Boolean) props.get( "mp3.copyright" ) )

						.booleanValue();

			if ( props.containsKey( "mp3.original" ) )

				original = ( (Boolean) props.get( "mp3.original" ) )

						.booleanValue();

			emphasis = "none";



			if ( props.containsKey( "title" ) )

				title = (String) props.get( "title" );

			if ( props.containsKey( "author" ) )

				artist = (String) props.get( "author" );

			if ( props.containsKey( "album" ) )

				album = (String) props.get( "album" );

			if ( props.containsKey( "date" ) )

				year = (String) props.get( "date" );

			if ( props.containsKey( "duration" ) )

				total = (long) Math.round( ( ( (Long) props.get( "duration" ) )

						.longValue() ) / 1000000 );

			if ( props.containsKey( "mp3.id3tag.genre" ) )

				genre = (String) props.get( "mp3.id3tag.genre" );

			if ( props.containsKey( "mp3.id3tag.track" ) ) {

				try {

					track = Integer.parseInt( (String) props

							.get( "mp3.id3tag.track" ) );

				} catch ( NumberFormatException e1 ) {

					// Not a number

				}

			}

		}

	}



	/**

	 * Load MP3 info from URL.

	 *

	 * @param input

	 * @throws IOException

	 * @throws UnsupportedAudioFileException

	 */

	protected void loadInfo( URL input ) throws IOException,

			UnsupportedAudioFileException {

		AudioFileFormat aff = AudioSystem.getAudioFileFormat( input );

		loadInfo( aff );

		loadShoutastInfo( aff );

	}



	/**

	 * Load Shoutcast info from AudioFileFormat.

	 *

	 * @param aff

	 * @throws IOException

	 * @throws UnsupportedAudioFileException

	 */

	protected void loadShoutastInfo( AudioFileFormat aff ) throws IOException,

			UnsupportedAudioFileException {

		String type = aff.getType().toString();

		if ( !type.equalsIgnoreCase( "mp3" ) )

			throw new UnsupportedAudioFileException( "Not MP3 audio format" );

		if ( aff instanceof TAudioFileFormat ) {

			Map props = ( (TAudioFileFormat) aff ).properties();

			// Try shoutcast meta data (if any).

			Iterator it = props.keySet().iterator();

			comments = new Vector();

			while ( it.hasNext() ) {

				String key = (String) it.next();

				if ( key.startsWith( "mp3.shoutcast.metadata." ) ) {

					String value = (String) props.get( key );

					key = key.substring( 23, key.length() );

					if ( key.equalsIgnoreCase( "icy-name" ) ) {

						title = value;

					} else if ( key.equalsIgnoreCase( "icy-genre" ) ) {

						genre = value;

					} else {

						comments.add( key + "=" + value );

					}

				}

			}

		}

	}



	public boolean getVBR() {

		return vbr;

	}



	public int getChannels() {

		return channels;

	}



	public String getVersion() {

		return version;

	}



	public String getEmphasis() {

		return emphasis;

	}



	public boolean getCopyright() {

		return copyright;

	}



	public boolean getCRC() {

		return crc;

	}



	public boolean getOriginal() {

		return original;

	}



	public String getLayer() {

		return layer;

	}



	public long getSize() {

		return size;

	}



	public String getLocation() {

		return location;

	}



	/*-- TagInfo Implementation --*/



	public int getSamplingRate() {

		return rate;

	}



	public int getBitRate() {

		return nominalbitrate;

	}



	public long getPlayTime() {

		return total;

	}



	public String getTitle() {

		return title;

	}



	public String getArtist() {

		return artist;

	}



	public String getAlbum() {

		return album;

	}



	public int getTrack() {

		return track;

	}



	public String getGenre() {

		return genre;

	}



	public Vector getComment() {

		return comments;

	}



	public String getYear() {

		return year;

	}



	/**

	 * Get channels mode.

	 *

	 * @return

	 */

	public String getChannelsMode() {

		return channelsMode;

	}



}